<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
<meta name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">

    <meta name="author" content="ZhangPing">





<title>Android混淆实现 | ZhangPing&#39;s Blog</title>



    <link rel="icon" href="/favicon.ico">




    <!-- stylesheets list from _config.yml -->
    
    <link rel="stylesheet" href="/css/style.css">
    



    <!-- scripts list from _config.yml -->
    
    <script src="/js/script.js"></script>
    
    <script src="/js/tocbot.min.js"></script>
    



    
    
        
    


<meta name="generator" content="Hexo 4.2.0"></head>
<body>
    <div class="wrapper">
        <header>
    <nav class="navbar">
        <div class="container">
            <div class="navbar-header header-logo"><a href="/">ZhangPing&#39;s Blog</a></div>
            <div class="menu navbar-right">
                
                    <a class="menu-item" href="/archives">Posts</a>
                
                    <a class="menu-item" href="/category">Categories</a>
                
                    <a class="menu-item" href="/tag">Tags</a>
                
                    <a class="menu-item" href="/about">About</a>
                
                <input id="switch_default" type="checkbox" class="switch_default">
                <label for="switch_default" class="toggleBtn"></label>
            </div>
        </div>
    </nav>

    
    <nav class="navbar-mobile" id="nav-mobile">
        <div class="container">
            <div class="navbar-header">
                <div>
                    <a href="/">ZhangPing&#39;s Blog</a><a id="mobile-toggle-theme">·&nbsp;Light</a>
                </div>
                <div class="menu-toggle" onclick="mobileBtn()">&#9776; Menu</div>
            </div>
            <div class="menu" id="mobile-menu">
                
                    <a class="menu-item" href="/archives">Posts</a>
                
                    <a class="menu-item" href="/category">Categories</a>
                
                    <a class="menu-item" href="/tag">Tags</a>
                
                    <a class="menu-item" href="/about">About</a>
                
            </div>
        </div>
    </nav>

</header>
<script>
    var mobileBtn = function f() {
        var toggleMenu = document.getElementsByClassName("menu-toggle")[0];
        var mobileMenu = document.getElementById("mobile-menu");
        if(toggleMenu.classList.contains("active")){
           toggleMenu.classList.remove("active")
            mobileMenu.classList.remove("active")
        }else{
            toggleMenu.classList.add("active")
            mobileMenu.classList.add("active")
        }
    }
</script>
        <div class="main">
            <div class="container">
    
    
        <div class="post-toc">
    <div class="tocbot-list">
    </div>
    <div class="tocbot-list-menu">
        <a class="tocbot-toc-expand" onclick="expand_toc()">Expand all</a>
        <a onclick="go_top()">Back to top</a>
        <a onclick="go_bottom()">Go to bottom</a>
    </div>
</div>

<script>
    document.ready(
        function () {
            tocbot.init({
                tocSelector: '.tocbot-list',
                contentSelector: '.post-content',
                headingSelector: 'h1, h2, h3, h4, h5',
                collapseDepth: 1,
                orderedList: false,
                scrollSmooth: true,
            })
        }
    )

    function expand_toc() {
        var b = document.querySelector(".tocbot-toc-expand");
        tocbot.init({
            tocSelector: '.tocbot-list',
            contentSelector: '.post-content',
            headingSelector: 'h1, h2, h3, h4, h5',
            collapseDepth: 6,
            orderedList: false,
            scrollSmooth: true,
        });
        b.setAttribute("onclick", "collapse_toc()");
        b.innerHTML = "Collapse all"
    }

    function collapse_toc() {
        var b = document.querySelector(".tocbot-toc-expand");
        tocbot.init({
            tocSelector: '.tocbot-list',
            contentSelector: '.post-content',
            headingSelector: 'h1, h2, h3, h4, h5',
            collapseDepth: 1,
            orderedList: false,
            scrollSmooth: true,
        });
        b.setAttribute("onclick", "expand_toc()");
        b.innerHTML = "Expand all"
    }

    function go_top() {
        window.scrollTo(0, 0);
    }

    function go_bottom() {
        window.scrollTo(0, document.body.scrollHeight);
    }

</script>
    

    
    <article class="post-wrap">
        <header class="post-header">
            <h1 class="post-title">Android混淆实现</h1>
            
                <div class="post-meta">
                    
                        Author: <a itemprop="author" rel="author" href="/">ZhangPing</a>
                    

                    
                        <span class="post-time">
                        Date: <a href="#">April 25, 2017&nbsp;&nbsp;1:10:00</a>
                        </span>
                    
                    
                        <span class="post-category">
                    Category:
                            
                                <a href="/categories/Android-%E7%9F%A5%E8%AF%86%E7%82%B9%E6%95%B4%E7%90%86/">Android-知识点整理</a>
                            
                        </span>
                    
                </div>
            
        </header>

        <div class="post-content">
            <p>今天被一位小伙伴问混淆的问题了，他原本是使用360加固。其实混淆的好处很明显：</p>
<p>1.代码混淆后可阅读性降低，反编译后破译程序难度提高（第三方有被脱壳的风险）<br>2.混淆后字节数减少，减少了应用了体积（第三方加固会增加几十到几百K不等的体积）<br>所以我把混淆的具体实现总结了出来与大家分享。</p>
<h3 id="一、build-gradle的配置"><a href="#一、build-gradle的配置" class="headerlink" title="一、build.gradle的配置"></a>一、build.gradle的配置</h3><p>对于proguardFiles这部分有两段，前一部分代表系统默认的android程序的混淆文件，该文件已经包含了基本的混淆声明，免去了我们很多事，这个文件的目录在 /tools/proguard/proguard-android.txt , 后一部分是我们项目里的自定义的混淆文件，目录就在 app/proguard-rules.txt</p>
<p>下面是gradle配置：（注意，minifyEnabled置为false的情况下，zipAlignEnabled 和 shrinkResources 也要置为false，否则会编译报错）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">buildTypes &#123;</span><br><span class="line">    release &#123;</span><br><span class="line">        <span class="comment">// 是否进行混淆</span></span><br><span class="line">        minifyEnabled <span class="keyword">true</span></span><br><span class="line">        <span class="comment">//不显示log</span></span><br><span class="line">        buildConfigField <span class="string">"boolean"</span>, <span class="string">"LOG_DEBUG"</span>, <span class="string">"false"</span></span><br><span class="line">        <span class="comment">//Zipalign优化</span></span><br><span class="line">        zipAlignEnabled <span class="keyword">true</span></span><br><span class="line">        <span class="comment">// 移除无用的resource文件</span></span><br><span class="line">        shrinkResources <span class="keyword">true</span></span><br><span class="line">        <span class="comment">//签名文件</span></span><br><span class="line">        signingConfig signingConfigs.release <span class="comment">//在gradle中引用的签名文件</span></span><br><span class="line">        <span class="comment">//对应的混淆文件</span></span><br><span class="line">        <span class="function">proguardFiles <span class="title">getDefaultProguardFile</span><span class="params">(<span class="string">'proguard-android.txt'</span>)</span>, 'proguard-rules.pro'</span></span><br><span class="line"><span class="function">    &#125;</span></span><br><span class="line"><span class="function">    debug</span>&#123;</span><br><span class="line">        debuggable <span class="keyword">true</span></span><br><span class="line">        signingConfig signingConfigs.debug</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="二、Android-混淆原则"><a href="#二、Android-混淆原则" class="headerlink" title="二、Android 混淆原则"></a>二、Android 混淆原则</h3><p>1.AndroidMainfest中的类不混淆，四大组件和Application的子类和Framework层下所有的类默认不会进行混淆。</p>
<p>2.反射用到的类不混淆</p>
<p>3.JNI方法不混淆</p>
<p>4.Parcelable的子类和Creator的静态成员变量不能混淆，否则会产生BadParcelableException异常。</p>
<p>5.有用到webView的JS调用也需要保证写的接口方法不混淆。</p>
<p>6.使用GSON、fastjson等框架时，所写的JSON对象类（即bean包下的所有类）不混淆，否则无法将JSON解析成对应的对象。</p>
<p>7.使用第三方开源库或者引用其他第三方的SDK包时，需要在混淆文件中加入对应的混淆规则。</p>
<p>8.R类里及其所有内部static类中的所有static变量字段不混淆。</p>
<p>备注：ProGuard在线说明手册</p>
<h3 id="三、混淆的常用语法"><a href="#三、混淆的常用语法" class="headerlink" title="三、混淆的常用语法"></a>三、混淆的常用语法</h3><p>1.-libraryjars class_path 应用的依赖包，如android-support-v4</p>
<p>2.-keep [,modifier,…] class_specification 不混淆某些类</p>
<p>3.-keepclassmembers [,modifier,…] class_specification不混淆类的成员</p>
<p>4.-keepclasseswithmembers [,modifier,…]class_specification 不混淆类及其成员</p>
<p>5.-keepnames class_specification 不混淆类及其成员名</p>
<p>6.-keepclassmembernames class_specification 不混淆类的成员名</p>
<p>7.-keepclasseswithmembernames class_specification 不混淆类及其成员名</p>
<p>8.-assumenosideeffects class_specification 假设调用不产生任何影响，在proguard代码优化时会将该调用remove掉。如system.out.println和Log.v等等</p>
<p>9.-dontwarn [class_filter] 不提示warnning</p>
<h3 id="四、混淆产生的文件"><a href="#四、混淆产生的文件" class="headerlink" title="四、混淆产生的文件"></a>四、混淆产生的文件</h3><p>1.mapping.txt</p>
<p>-printmapping mapping.txt</p>
<p>表示混淆前后代码的对照表，这个文件非常重要。如果你的代码混淆后会产生bug的话，log提示中是混淆后的代码，希望定位到源代码的话就可以根据mapping.txt反推。<br>每次发布都要保留它方便该版本出现问题时调出日志进行排查，它可以根据版本号或是发布时间命名来保存或是放进代码版本控制中。</p>
<p>2.dump.txt</p>
<p>-dump class_files.txt</p>
<p>描述apk内所有class文件的内部结构。</p>
<p>3.seeds.txt</p>
<p>-printseeds seeds.txt</p>
<p>列出了没有被混淆的类和成员。</p>
<p>4.usage.txt</p>
<p>-printusage unused.txt</p>
<p>列出了源代码中被删除在apk中不存在的代码。</p>
<p>以上文件需要在android工程中混淆配置文件：proguard-rules.pro中配置</p>
<h3 id="五、-项目混淆配置"><a href="#五、-项目混淆配置" class="headerlink" title="五、 项目混淆配置"></a>五、 项目混淆配置</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br></pre></td><td class="code"><pre><span class="line">proguard-rules.pro 文件的配置如下：</span><br><span class="line">#指定代码的压缩（proguard对代码进行迭代优化的次数0-7）等级Android中一般设置为5</span><br><span class="line">-optimizationpasses 5</span><br><span class="line">#包名不使用大小写混合</span><br><span class="line">-dontusemixedcaseclassnames</span><br><span class="line"># 不混淆第三方引用的库</span><br><span class="line">-dontskipnonpubliclibraryclasses</span><br><span class="line"># 不做预校验</span><br><span class="line">-dontpreverify</span><br><span class="line"># 忽略警告</span><br><span class="line">-ignorewarning</span><br><span class="line">#apk 包内所有 class 的内部结构</span><br><span class="line">-dump class_files.txt</span><br><span class="line">#未混淆的类和成员</span><br><span class="line">-printseeds seeds.txt</span><br><span class="line">#列出从 apk 中删除的代码</span><br><span class="line">-printusage unused.txt</span><br><span class="line">#混淆前后的映射</span><br><span class="line">-printmapping mapping.txt</span><br><span class="line"># 保持Activity类及其子类不被混淆</span><br><span class="line">-keep public class * extends android.app.Activity</span><br><span class="line"># 保持Application类及其不被混淆</span><br><span class="line">-keep public class * extends android.app.Application</span><br><span class="line"># 保持Service类及其子类不被混淆</span><br><span class="line">-keep public class * extends android.app.Service</span><br><span class="line"># 保持BroadcastReceiver类及其不被混淆</span><br><span class="line">-keep public class * extends android.content.BroadcastReceiver</span><br><span class="line"># 保持ContentProvider类及其子类不被混淆</span><br><span class="line">-keep public class * extends android.content.ContentProvider</span><br><span class="line"># 保持BackupAgentHelper类及其子类不被混淆</span><br><span class="line">-keep public class * extends android.app.backup.BackupAgentHelper</span><br><span class="line"># 保持Preference类及其子类不被混淆</span><br><span class="line">-keep public class * extends android.preference.Preference</span><br><span class="line"># 保持Fragment类及其子类不被混淆</span><br><span class="line">-keep public class * extends android.app.Fragment</span><br><span class="line">#保持引用v4包下Fragment及其子类不被混淆</span><br><span class="line">-keep public class * extends android.support.v4.app.Fragment</span><br><span class="line">#保持 Serializable类及其实现类不被混淆</span><br><span class="line">-keepnames class * implements java.io.Serializable</span><br><span class="line"># 如果引用了v4或者v7包</span><br><span class="line">-dontwarn android.support.**</span><br><span class="line"># 保持 native 方法不被混淆</span><br><span class="line">-keepclasseswithmembernames class * &#123;</span><br><span class="line">    native &lt;methods&gt;;</span><br><span class="line">&#125;</span><br><span class="line">#保护注解</span><br><span class="line">-keepattributes *Annotation*</span><br><span class="line">-keep class * extends java.lang.annotation.Annotation &#123;*;&#125;</span><br><span class="line"># 不混淆内部类</span><br><span class="line">-keepattributes InnerClasses</span><br><span class="line">#不混淆资源类即R文件</span><br><span class="line">-keepclassmembers class **.R$* &#123;</span><br><span class="line">    public static &lt;fields&gt;;</span><br><span class="line">&#125;</span><br><span class="line">#避免混淆泛型 如果混淆报错建议关掉</span><br><span class="line">-keepattributes Signature</span><br><span class="line"># 保持枚举 enum 类不被混淆</span><br><span class="line">-keepclassmembers enum * &#123;</span><br><span class="line">   public static **[] values();</span><br><span class="line">   public static ** valueOf(java.lang.String);</span><br><span class="line">&#125;</span><br><span class="line"># 保持自定义控件类不被混淆</span><br><span class="line">-keepclasseswithmembers class * &#123;</span><br><span class="line">   public &lt;init&gt;(android.content.Context, android.util.AttributeSet);</span><br><span class="line">&#125;</span><br><span class="line"># 保持自定义控件类不被混淆</span><br><span class="line">-keepclasseswithmembers class * &#123;</span><br><span class="line">   public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int);</span><br><span class="line">&#125;</span><br><span class="line"># 保持Activity中参数类型为View的所有方法</span><br><span class="line">-keepclassmembers class * extends android.app.Activity &#123;</span><br><span class="line">   public void *(android.view.View);</span><br><span class="line">&#125;</span><br><span class="line">#保持所有bean类（即bean包下所有类）都不被混淆</span><br><span class="line">-keep class android.launcher.bean.**&#123;</span><br><span class="line">    *;</span><br><span class="line">&#125;</span><br><span class="line">#所有View的子类及其子类的get、set方法都不进行混淆</span><br><span class="line">-keep public class * extends android.view.View &#123;</span><br><span class="line">          public &lt;init&gt;(android.content.Context);</span><br><span class="line">          public &lt;init&gt;(android.content.Context, android.util.AttributeSet);</span><br><span class="line">          public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int);</span><br><span class="line">          public void set*(...);</span><br><span class="line">  &#125;</span><br><span class="line"># 保持包含org.json.JSONObject参数的构造方法的类</span><br><span class="line">-keepclassmembers class * &#123;</span><br><span class="line">   public &lt;init&gt; (org.json.JSONObject);</span><br><span class="line">&#125;</span><br><span class="line"># 有用到WEBView的JS调用接口不被混淆</span><br><span class="line">-keepclassmembers class fqcn.of.javascript.interface.for.webview &#123;</span><br><span class="line">  public *;</span><br><span class="line">&#125;</span><br><span class="line">#移除log 测试了下没有用还是建议自己定义一个开关控制是否输出日志</span><br><span class="line">-assumenosideeffects class android.util.Log &#123;</span><br><span class="line">         public static boolean isLoggable(java.lang.String, int);</span><br><span class="line">         public static int v(...);</span><br><span class="line">         public static int i(...);</span><br><span class="line">         public static int w(...);</span><br><span class="line">         public static int d(...);</span><br><span class="line">         public static int e(...);</span><br><span class="line">  &#125;</span><br><span class="line">#友盟推送的混淆配置</span><br><span class="line">-dontwarn com.taobao.**</span><br><span class="line">-dontwarn anet.channel.**</span><br><span class="line">-dontwarn anetwork.channel.**</span><br><span class="line">-dontwarn org.android.**</span><br><span class="line">-dontwarn org.apache.thrift.**</span><br><span class="line">-dontwarn com.xiaomi.**</span><br><span class="line">-dontwarn com.huawei.**</span><br><span class="line">-keep class com.taobao.** &#123;*;&#125;</span><br><span class="line">-keep class org.android.** &#123;*;&#125;</span><br><span class="line">-keep class anetwork.channel.**&#123;*;&#125;</span><br><span class="line">-keep class anet.channel.** &#123;*;&#125;</span><br><span class="line">-keep class com.umeng.** &#123;*;&#125;</span><br><span class="line">-keep class com.xiaomi.** &#123;*;&#125;</span><br><span class="line">-keep class com.huawei.** &#123;*;&#125;</span><br><span class="line">-keep class org.apache.thrift.** &#123;*;&#125;</span><br><span class="line">-keep public class **.R$*&#123;</span><br><span class="line">   public static final int *;</span><br><span class="line">&#125;</span><br><span class="line">#友盟统计的混淆配置1、R文件的混淆保护2、枚举混淆3、JSON混淆</span><br><span class="line">#因为上面都有配置故不做重复配置</span><br><span class="line"></span><br><span class="line">#展示互动混淆配置</span><br><span class="line">-dontwarn com.gensee.**</span><br><span class="line">-keep class com.gensee.**&#123;*;&#125;</span><br><span class="line">#universal-image-loader包</span><br><span class="line">-keep class com.nostra13.universalimageloader.** &#123; *; &#125;</span><br><span class="line">#CC视频 jar包</span><br><span class="line">-dontwarn com.bokecc.sdk.mobile.**</span><br><span class="line">-keep public class com.bokecc.sdk.mobile.**&#123;*;&#125;</span><br><span class="line">-keep public interface com.bokecc.sdk.mobile.**&#123;*;&#125;</span><br><span class="line">#混淆保护自己项目的部分代码以及引用的第三方jar包library</span><br><span class="line">#-libraryjars libs&#x2F;universal-image-loader-1.9.5.jar</span><br><span class="line">#-libraryjars libs&#x2F;opensdk.jar</span><br><span class="line">#-libraryjars libs&#x2F;butelCommConnect.jar</span><br><span class="line">#自定义的下拉刷新GridView</span><br><span class="line">-keep class com.chanven.lib.cptr.**&#123;*;&#125;</span><br><span class="line">#Volley</span><br><span class="line">-dontwarn com.android.volley.jar.**</span><br><span class="line">-keep class com.android.volley.**&#123;*;&#125;</span><br></pre></td></tr></table></figure>

<p>注意：javabean文件一定要keep掉，不能被混淆。</p>
<h3 id="六、多渠道打包方法"><a href="#六、多渠道打包方法" class="headerlink" title="六、多渠道打包方法"></a>六、多渠道打包方法</h3><p>我们打开要打包的module下的build配置文件这里会有两个方法,一个普通方法,一个快捷方法。</p>
<ol>
<li>普通方法：</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">roductFlavors &#123;</span><br><span class="line">  wandoujia &#123;</span><br><span class="line">  	manifestPlaceholders = [UMENG_CHANNEL_VALUE: <span class="string">"wandoujia"</span>]</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  baidu &#123;</span><br><span class="line">  	manifestPlaceholders = [UMENG_CHANNEL_VALUE: <span class="string">"baidu"</span>]</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  c360 &#123;</span><br><span class="line">  	manifestPlaceholders = [UMENG_CHANNEL_VALUE: <span class="string">"c360"</span>]</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  uc &#123;</span><br><span class="line">  	manifestPlaceholders = [UMENG_CHANNEL_VALUE: <span class="string">"uc"</span>]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>2：快捷方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">productFlavors &#123; </span><br><span class="line">            wandoujia &#123;&#125;  </span><br><span class="line">            baidu &#123;&#125;</span><br><span class="line">            c360 &#123;&#125;</span><br><span class="line">            ...</span><br><span class="line">            roductFlavors.all &#123; flavor -&gt;</span><br><span class="line">                flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]</span><br><span class="line">            &#125; </span><br><span class="line">       &#125;</span><br></pre></td></tr></table></figure>

<p>注意：UMENG_CHANNEL_VALUE ,就是动态修改Androidmanifest中的value,分不同的渠道。</p>
<h3 id="七、-命令行打包配置"><a href="#七、-命令行打包配置" class="headerlink" title="七、 命令行打包配置"></a>七、 命令行打包配置</h3><p>首先要配置好gradle的环境变量方便我们在Terminal的方式(cmd应该也可以,没试过),运行打包命令,如果不知道的话,我先贴出配置方法吧(其实跟java配置环境变量一样一样的)</p>
<p>先找到gralde的根目录，在系统变量里添加两个环境变量：<br>  变量名为：GRADLE_HOME，变量值就为gradle的根目录；<br>  所以变量值为：C:\Users\ping.gradle\wrapper\dists\gradle-2.1-all\27drb4udbjf4k88eh2ffdc0n55\gradle-2.1<br>  还有一个在系统变量里PATH里面添加gradle的bin目录<br>  我的就是C:\Users\ping.gradle\wrapper\dists\gradle-2.1-all\27drb4udbjf4k88eh2ffdc0n55\gradle-2.1\bin<br>这里配置完成了，接着在Terminal中敲下 gradle assembleRelease 就可以一次性生成所有的渠道包了。所有生成的apk在项目的 build\outputs\apk 下。</p>
<h3 id="八、-基线版本保存"><a href="#八、-基线版本保存" class="headerlink" title="八、 基线版本保存"></a>八、 基线版本保存</h3><p>在打包完成后需要保存基线版本，关于基线版本需要保存的文件说明：</p>
<p>1.如果项目集成了tinker那么需要保留app/build/bakApk文件夹，留作热部署时的基线参考。</p>
<p>2.项目如果集成了友盟统计那么需要保留app/build/outputs文件夹，主要保留mapping文件，因为mapping文件存储了代码混淆对应。通过友盟统计上传对应版本的mapping文件能准确定位发生bug的位置。</p>

        </div>

        
            <section class="post-copyright">
                
                    <p class="copyright-item">
                        <span>Author:</span>
                        <span>ZhangPing</span>
                    </p>
                
                
                    <p class="copyright-item">
                        <span>Permalink:</span>
                        <span><a href="https://zhangpingv5.gitee.io/2017/04/25/Android%E6%B7%B7%E6%B7%86%E5%AE%9E%E7%8E%B0/">https://zhangpingv5.gitee.io/2017/04/25/Android%E6%B7%B7%E6%B7%86%E5%AE%9E%E7%8E%B0/</a></span>
                    </p>
                
                
                    <p class="copyright-item">
                        <span>License:</span>
                        <span>转载请注明出处</span>
                    </p>
                
                
                     <p class="copyright-item">
                         <span>Slogan:</span>
                         <span>Self-descipline grants me freedom.</span>
                     </p>
                

            </section>
        
        <section class="post-tags">
            <div>
                <span>Tag(s):</span>
                <span class="tag">
                    
                    
                        <a href="/tags/%E6%B7%B7%E6%B7%86/"># 混淆</a>
                    
                        
                </span>
            </div>
            <div>
                <a href="javascript:window.history.back();">back</a>
                <span>· </span>
                <a href="/">home</a>
            </div>
        </section>
        <section class="post-nav">
            
                <a class="prev" rel="prev" href="/2017/05/07/AAPTerr/">AAPTerr ERROR Unable to open PNG file</a>
            
            
            <a class="next" rel="next" href="/2016/11/22/Volley%20io%E8%AF%BB%E5%8F%96%E7%BC%93%E5%AD%98%E9%83%A8%E5%88%86%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/">Volley io读取缓存部分中文乱码问题</a>
            
        </section>


    </article>
</div>

        </div>
        <footer id="footer" class="footer">
    <div class="copyright">
        <span>© ZhangPing | Powered by <a href="https://hexo.io" target="_blank">Hexo</a> & <a href="https://github.com/Siricee/hexo-theme-Chic" target="_blank">Chic</a></span>
    </div>
</footer>

    </div>
</body>
</html>
